package com.atguigu.tingshu.search.service.impl;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldSort;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.aggregations.Aggregate;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Suggestion;
import co.elastic.clients.util.ObjectBuilder;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.tingshu.album.client.AlbumInfoFeignClient;
import com.atguigu.tingshu.album.client.CategoryFeignClient;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.PinYinUtils;
import com.atguigu.tingshu.model.album.*;
import com.atguigu.tingshu.model.search.AlbumInfoIndex;
import com.atguigu.tingshu.model.search.AttributeValueIndex;
import com.atguigu.tingshu.model.search.SuggestIndex;
import com.atguigu.tingshu.query.search.AlbumIndexQuery;
import com.atguigu.tingshu.search.repository.AlbumIndexRepository;
import com.atguigu.tingshu.search.repository.SuggestIndexRepository;
import com.atguigu.tingshu.search.service.SearchService;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.atguigu.tingshu.vo.search.AlbumInfoIndexVo;
import com.atguigu.tingshu.vo.search.AlbumSearchResponseVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.elasticsearch.core.suggest.Completion;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;


@Slf4j
@Service
@RefreshScope//+@Value("${ranking.dimension.array}")
@SuppressWarnings({"all"})
public class SearchServiceImpl implements SearchService {

    @Autowired
    private AlbumInfoFeignClient albumInfoFeignClient;
    @Autowired
    private CategoryFeignClient categoryFeignClient;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    //  利用es 的客户端操作对象，保存albumInfoIndex！ElasticsearchRepository 在启动的时候，能够根据实体类帮我自动生成映射Index!
    @Autowired
    private AlbumIndexRepository albumIndexRepository;
    @Autowired
    private ElasticsearchClient elasticsearchClient;
    //索引库
    @Autowired
    private SuggestIndexRepository suggestIndexRepository;
    //    @RefreshScope 热部署
    //  软编码形式！
    //@Value("${ranking.dimension.array}")
    //private String arrays;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void upperAlbum(Long albumId) {
        //本质就是获取各个表的数据然后封装  然后给AlbumInfoIndex  赋值最终存到es中
        AlbumInfoIndex albumInfoIndex = new AlbumInfoIndex();
        //优化多线程并进行集合封装
        CompletableFuture<AlbumInfo> albumInfoCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //赋值
            Result<AlbumInfo> albumInfoResult = albumInfoFeignClient.getAlbumInfo(albumId);
            //判断当前这个结果是否为空
            Assert.notNull(albumInfoResult, "查询专辑结果集失败");
            AlbumInfo albumInfo = albumInfoResult.getData();
            //获取专辑信息
            Assert.notNull(albumInfo, "查询专辑结果集失败");
            //有一样的属性直接拷贝
            BeanUtils.copyProperties(albumInfo, albumInfoIndex);
            //albumInfo 包含属性值集合
            List<AlbumAttributeValue> albumAttributeValueVoList = albumInfo.getAlbumAttributeValueVoList();
            //判断
            if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) {
                //  循环遍历集合中的部分属性字段值，赋值
                List<AttributeValueIndex> attributeValueIndexList = albumAttributeValueVoList.stream().map(albumAttributeValue ->
                {
                    AttributeValueIndex attributeValueIndex = new AttributeValueIndex();
                    attributeValueIndex.setAttributeId(albumAttributeValue.getAttributeId());
                    attributeValueIndex.setValueId(albumAttributeValue.getValueId());
                    return attributeValueIndex;
                }).collect(Collectors.toList());
                //赋值
                albumInfoIndex.setAttributeValueIndexList(attributeValueIndexList);
            }
            //远程调用
            //获取剩余信息赋值的数据还有呢！ 播放量，统计，订阅等没有给数据.
            Result<AlbumStatVo> albumStatVoResult = albumInfoFeignClient.getAlbumStatVo(albumId);
            Assert.notNull(albumStatVoResult, "查询用户信息失败！");
            AlbumStatVo trackStatList = albumStatVoResult.getData();
            Assert.notNull(trackStatList, "查询用户信息失败！");
            //远程调用根据专辑id进行赋值
            BeanUtils.copyProperties(trackStatList, albumInfoIndex);
            return albumInfo;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("查询结果集失败", throwable);
            return null;
        });
        //查询分类数据 根据三级分类id 查询视图数据 视图包含了一级，二级，三级分类Id
        CompletableFuture<Integer> categoryCompletableFuture = albumInfoCompletableFuture.thenApplyAsync(albumInfo -> {
            if (albumInfo == null) {
                throw new IllegalArgumentException("albumInfo 不能为空");
            }
            //远程调用获取分类视图数据
            Result<BaseCategoryView> baseCategoryViewResult = categoryFeignClient.getCategoryView(albumInfo.getCategory3Id());
            //判断
            Assert.notNull(baseCategoryViewResult, "查询分类数据失败");
            BaseCategoryView baseCategoryView = baseCategoryViewResult.getData();
            //判断
            Assert.notNull(baseCategoryView, "查询分类数据失败");
            //赋值
            albumInfoIndex.setCategory1Id(baseCategoryView.getCategory1Id());
            albumInfoIndex.setCategory2Id(baseCategoryView.getCategory2Id());
            //赋值成功返回1
            return 1;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("查询视图失败", throwable);
            return 0;
        });
        //获取用户信息
        CompletableFuture<Integer> userCompletableFuture = albumInfoCompletableFuture.thenApplyAsync(albumInfo -> {
            //远程调用
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfo(albumInfo.getUserId());
            Assert.notNull(userInfoVoResult, "查询用户信息失败1");
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            Assert.notNull(userInfoVo, "查询用户信息失败2");

            //  赋值主播名称
            albumInfoIndex.setAnnouncerName(userInfoVo.getNickname());
            return 1;
        }, threadPoolExecutor).exceptionally(throwable -> {
            log.error("查询用户信息失败!", throwable);
            return 0;
        });
//        //  赋值的数据还有呢！ 播放量，统计，订阅等没有给数据.
//        //  需要根据专辑Id 获取统计表中的数据.
//        albumInfoIndex.setBuyStatNum(new Random().nextInt(10000));
//        albumInfoIndex.setCommentStatNum(new Random().nextInt(10000));
//        albumInfoIndex.setSubscribeStatNum(new Random().nextInt(10000));
//        albumInfoIndex.setPlayStatNum(new Random().nextInt(10000));
        //  还有一个热度排名
        albumInfoIndex.setHotScore((double) new Random().nextInt(10000));

        //判断上面是否都获取成功
        try {
            if (null == albumInfoCompletableFuture.get() || 0 == categoryCompletableFuture.get() || 0 == userCompletableFuture.get()) {
                return;
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
        //多任务组合 要不然无效
        CompletableFuture.allOf(
                albumInfoCompletableFuture,
                categoryCompletableFuture,
                userCompletableFuture
        ).join();
        //保存数据
        albumIndexRepository.save(albumInfoIndex);

        //保存专辑的题词库
        //构建一个提出库的实体类
        SuggestIndex suggestIndex = new SuggestIndex();
        //赋值 按照专辑标题进行保存 !
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndex.setTitle(albumInfoIndex.getAlbumTitle());
        suggestIndex.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumTitle()}));
        suggestIndex.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumTitle())}));
        suggestIndex.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumTitle())}));
        suggestIndexRepository.save(suggestIndex);
        //  专辑简介提词
        SuggestIndex suggestIndexIntro = new SuggestIndex();
        suggestIndex.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndexIntro.setTitle(albumInfoIndex.getAlbumIntro());
        suggestIndexIntro.setKeyword(new Completion(new String[]{albumInfoIndex.getAlbumIntro()}));
        suggestIndexIntro.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAlbumIntro())}));
        suggestIndexIntro.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAlbumIntro())}));
        suggestIndexRepository.save(suggestIndexIntro);
        //  作者提词
        SuggestIndex suggestIndexName = new SuggestIndex();
        suggestIndexName.setId(UUID.randomUUID().toString().replaceAll("-", ""));
        suggestIndexName.setTitle(albumInfoIndex.getAnnouncerName());
        suggestIndexName.setKeyword(new Completion(new String[]{albumInfoIndex.getAnnouncerName()}));
        suggestIndexName.setKeywordPinyin(new Completion(new String[]{PinYinUtils.toHanyuPinyin(albumInfoIndex.getAnnouncerName())}));
        suggestIndexName.setKeywordSequence(new Completion(new String[]{PinYinUtils.getFirstLetter(albumInfoIndex.getAnnouncerName())}));
        suggestIndexRepository.save(suggestIndexName);

    }

    @Override
    public void lowerAlbum(Long albumId) {
        //删除数据
        albumIndexRepository.deleteById(albumId);
    }

    @Override
    public AlbumSearchResponseVo search(AlbumIndexQuery albumIndexQuery) {
        //本质就是获取实体类属性进行赋值
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //调用es的客户端进行检索
        //第一个参数就是封装dsl 语句, 第二个参数是返回结果集的类
        SearchRequest searchRequest = this.buildDslQuery(albumIndexQuery);
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(searchRequest, AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //封装部分返回值结果集数据:
        albumSearchResponseVo = this.parseSearchResponse(searchResponse);

        /*
            private Long total;//总记录数
            private Integer pageSize;//每页显示的内容
            private Integer pageNo;//当前页面
            private Long totalPages;
         */
        albumSearchResponseVo.setTotal(searchResponse.hits().total().value());
        albumSearchResponseVo.setPageSize(albumIndexQuery.getPageSize());
        albumSearchResponseVo.setPageNo(albumIndexQuery.getPageNo());
        //总页数; 10 3 4 | 9 3 3 (total%pageSize==0?total\pageSize:total\pageSize+1)
        long totalPages = (albumSearchResponseVo.getTotal() + albumSearchResponseVo.getPageSize() - 1) / albumSearchResponseVo.getPageNo();
        albumSearchResponseVo.setTotalPages(totalPages);

        //返回数据
        return albumSearchResponseVo;
    }

    @Override
    public List<String> completeSuggest(String keyword) {
        //声明一个集合
        List<String> list = new ArrayList<>();
        //1.创建dsl语句 2.获取数据
        SearchResponse<SuggestIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(s -> s.index("suggestinfo")
                            .suggest(s1 -> s1.suggesters("keyword-suggest",
                                            s2 -> s2.prefix(keyword).completion(c -> c.field("keyword")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordPinyin-suggest", s3 -> s3.prefix(keyword)
                                            .completion(c -> c.field("keywordPinyin")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                                    .suggesters("keywordSequence-suggest", s3 -> s3.prefix(keyword)
                                            .completion(c -> c.field("keywordSequence")
                                                    .skipDuplicates(true)
                                                    .fuzzy(f -> f.fuzziness("auto"))
                                                    .size(10)))
                            )
                    ,
                    SuggestIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        //2.获取结果集
        //        searchResponse.suggest().get("keyword-suggest");
        //        searchResponse.suggest().get("keywordPinyin-suggest");
        //        searchResponse.suggest().get("keywordSequence-suggest");
        //        List<String> l1 = this.getParseResultData("keyword-suggest");
        //        List<String> l2 = this.getParseResultData("keywordPinyin-suggest");
        //        List<String> l3 = this.getParseResultData("keywordSequence-suggest");

        //汇总
        list.addAll(this.getParseResultData(searchResponse, "keyword-suggest"));
        list.addAll(this.getParseResultData(searchResponse, "keywordPinyin-suggest"));
        list.addAll(this.getParseResultData(searchResponse, "keywordSequence-suggest"));
        //返回数据
        return list;
    }

    @Override
    public List<Map<String, Object>> channel(Long category1Id) {
        //  已知一级分类Id数据; map.put("baseCategory3","") map.put("list","");
        //  根据一级分类Id 查询三级分类列表;
        Result<List<BaseCategory3>> baseCategory3Result = categoryFeignClient.findTopBaseCategory3(category1Id);
        Assert.notNull(baseCategory3Result, "查询三级分类列表失败！");
        List<BaseCategory3> baseCategory3List = baseCategory3Result.getData();
        Assert.notNull(baseCategory3List, "查询三级分类列表失败！");
        //  将baseCategory3List 这个集合变为map集合; key=category3Id value=BaseCategory3;
        Map<Long, BaseCategory3> category3Map = baseCategory3List.stream().collect(Collectors.toMap(BaseCategory3::getId, baseCategory3 -> baseCategory3));
        //  查询的是：一级分类下的三级分类对应的专辑集合列表
        //  List<Long> category3IdList = baseCategory3List.stream().map(BaseCategory3::getId).collect(Collectors.toList());
        //  List<Long> 转换为List<FieldValue>
        //  List<FieldValue> valueList = category3IdList.stream().map(category3Id -> FieldValue.of(category3Id)).collect(Collectors.toList());
        List<FieldValue> fieldValueIdList = baseCategory3List.stream().map(baseCategory3 -> FieldValue.of(baseCategory3.getId())).collect(Collectors.toList());
        //  动态生成dsl语句;
        SearchResponse<AlbumInfoIndex> searchResponse = null;
        try {
            searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                            .query(q -> q.terms(t -> t.field("category3Id").terms(ts -> ts.value(fieldValueIdList))))
                            .aggregations("category3Id_agg", a -> a.terms(ts -> ts.field("category3Id"))
                                    .aggregations("topSix_agg", ag -> ag.topHits(th -> th.size(10)
                                            .sort(st -> st.field(fd -> fd.field("hotScore").order(SortOrder.Desc))))))
                    ,
                    AlbumInfoIndex.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //  获取数据;
        Aggregate aggregate = searchResponse.aggregations().get("category3Id_agg");
        List<Map<String, Object>> mapList = aggregate.lterms().buckets().array().stream().map(bucket -> {
            //  获取到三级分类Id
            long category3Id = bucket.key();
            //  创建map集合;
            Map<String, Object> map = new HashMap<>();
            //  获取专辑信息
            List<AlbumInfoIndex> albumInfoIndexList = bucket.aggregations().get("topSix_agg").topHits().hits().hits().stream().map(hit -> {
                //  获取专辑信息
                String strJson = hit.source().toString();
                //  数据类型专辑;
                AlbumInfoIndex albumInfoIndex = JSONObject.parseObject(strJson, AlbumInfoIndex.class);
                //  返回数据;
                return albumInfoIndex;
            }).collect(Collectors.toList());
            //  存储专辑列表信息;
            map.put("list", albumInfoIndexList);
            //  存储三级分类对象;
            map.put("baseCategory3", category3Map.get(category3Id));
            return map;
        }).collect(Collectors.toList());
        //  返回数据
        return mapList;
    }

    @Override
    public void updateLatelyAlbumRanking() {
        //  1.  将数据从es中获取到； a. 分类Id 需要获取到； b. 排序维度
        //  查询所有的一级分类Id;
        Result<List<BaseCategory1>> baseCategory1ListResult = categoryFeignClient.findAllBaseCategory1();
        Assert.notNull(baseCategory1ListResult, "查询一级分类列表失败！");
        List<BaseCategory1> baseCategory1List = baseCategory1ListResult.getData();
        Assert.notNull(baseCategory1List, "查询一级分类列表失败！");
        //  因为排序的维度是固定的：那么就可以直接写在项目代码中了.
       // System.out.println(arrays);
       // String[] rankingArrays = arrays.split(",");
        //  属于硬编码！
        String[] rankingArrays = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
        //  执行dsl语句
        for (BaseCategory1 baseCategory1 : baseCategory1List) { // category1Id=1..15;
            for (String ranking : rankingArrays) {
                SearchResponse<AlbumInfoIndex> searchResponse = null;
                try {
                    searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
                                    //  .query(q -> q.match(m -> m.field("category1Id").query(baseCategory1.getId())))

                                    .sort(st -> st.field(f -> f.field(ranking).order(SortOrder.Desc)))
                            ,
                            AlbumInfoIndex.class);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                //  2.  将获取到的数据存储到redis中;(hash)
                //  获取的集合列表；
                List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
                //  存储到缓存
                this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId(),ranking,albumInfoIndexList);
            }
            //  2.  将获取到的数据存储到redis中;(hash)
        }


    }
//@Override
//public void updateLatelyAlbumRanking() {
//    //  1.  将数据从es中获取到； a. 分类Id 需要获取到； b. 排序维度
//    //  查询所有的一级分类Id;
//    Result<List<BaseCategory1>> baseCategory1ListResult = categoryFeignClient.findAllBaseCategory1();
//    Assert.notNull(baseCategory1ListResult, "查询一级分类列表失败！");
//    List<BaseCategory1> baseCategory1List = baseCategory1ListResult.getData();
//    Assert.notNull(baseCategory1List, "查询一级分类列表失败！");
//    //  因为排序的维度是固定的：那么就可以直接写在项目代码中了.
//    System.out.println(arrays);
//    String[] rankingArrays = arrays.split(",");
//    //  属于硬编码！
//    String[] rankingDimensionArray = new String[]{"hotScore", "playStatNum", "subscribeStatNum", "buyStatNum", "commentStatNum"};
//    //  执行dsl语句
//    for (BaseCategory1 baseCategory1 : baseCategory1List) { // category1Id=1..15;
//        for (String ranking : rankingArrays) {
//            SearchResponse<AlbumInfoIndex> searchResponse = null;
//            try {
//                searchResponse = elasticsearchClient.search(s -> s.index("albuminfo")
//                                //  .query(q -> q.match(m -> m.field("category1Id").query(baseCategory1.getId())))
//
//                                .sort(st -> st.field(f -> f.field(ranking).order(SortOrder.Desc)))
//                        ,
//                        AlbumInfoIndex.class);
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//            //  2.  将获取到的数据存储到redis中;(hash)
//            //  获取的集合列表；
//            List<AlbumInfoIndex> albumInfoIndexList = searchResponse.hits().hits().stream().map(Hit::source).collect(Collectors.toList());
//            //  存储到缓存
//            this.redisTemplate.opsForHash().put(RedisConstant.RANKING_KEY_PREFIX+baseCategory1.getId(),ranking,albumInfoIndexList);
//        }
//        //  2.  将获取到的数据存储到redis中;(hash)
//    }
//
//
//}
    @Override
    public List<AlbumInfoIndex> findRankingList(Long category1Id, String rangking) {
        //  hget key field;
        List<AlbumInfoIndex> albumInfoIndexList = (List<AlbumInfoIndex>) redisTemplate.opsForHash().get(RedisConstant.RANKING_KEY_PREFIX + category1Id, rangking);
        return albumInfoIndexList;
    }

    private Collection<String> getParseResultData(SearchResponse<SuggestIndex> searchResponse, String key) {
        //返回集合数据
        List<Suggestion<SuggestIndex>> suggestions = searchResponse.suggest().get(key);
        //判断集合
        if (!CollectionUtils.isEmpty(suggestions)) {
            List<String> list = suggestions.get(0).completion().options().stream().map(suggest -> {
                        return suggest.source().getTitle();
                    }
            ).collect(Collectors.toList());
            //返回数据
            return list;
        }
        //默认为空
        return new ArrayList<>();
    }

    private AlbumSearchResponseVo parseSearchResponse(SearchResponse<AlbumInfoIndex> searchResponse) {
        //创建对象
        AlbumSearchResponseVo albumSearchResponseVo = new AlbumSearchResponseVo();
        //只赋值一个属性private List<AlbumInfoIndex> list = new ArrayList<>();
        List<AlbumInfoIndexVo> albumInfoIndexVoList = searchResponse.hits().hits().stream().map(hit -> {
            //创建数据对象
            AlbumInfoIndexVo albumInfoIndexVo = new AlbumInfoIndexVo();
            AlbumInfoIndex albumInfoIndex = hit.source();
            //属性拷贝
            BeanUtils.copyProperties(albumInfoIndex, albumInfoIndexVo);
            //判断是否为高亮数据
            if (null != hit.highlight().get("albumTitle")) {
                //有高亮数据
                String albumTitle = hit.highlight().get("albumTitle").get(0);
                albumInfoIndexVo.setAlbumTitle(albumTitle);
            }
            //返回数据
            return albumInfoIndexVo;
        }).collect(Collectors.toList());
        //赋值
        albumSearchResponseVo.setList(albumInfoIndexVoList);
        //返回对象
        return albumSearchResponseVo;

    }


    private SearchRequest buildDslQuery(AlbumIndexQuery albumIndexQuery) {
        //判断用户是根据那个方法进行检索
        //创建一个SearchRequest对象:
        SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder();
        searchRequestBuilder.index("albuminfo");
        BoolQuery.Builder boolQueryBuilder = new BoolQuery.Builder();

        //1.判断用户到底是根据那个条件进行检索
        //  检索入口：一个是全文检索keyword； 一个是根据分类Id检修检索！
        String keyword = albumIndexQuery.getKeyword();
        //设置检索数据
        if (!StringUtils.isEmpty(keyword)) {
            //设计检索数据
            boolQueryBuilder.should(s -> s.match(m -> m.field("albumTitle").query(keyword)))
                    .should(s -> s.match(m -> m.field("albumIntro").query(keyword)))
                    .should(s -> s.match(m -> m.field("announcerName").query(keyword)));
            //根据关键字检索 需要加高亮显示
            searchRequestBuilder.highlight(h -> h.fields("albumTitle", f -> f.preTags("<span style=color:red>").postTags("</span>")));
        }
        //2.判断用户是根据那个分类Id进行检索
        if (null != albumIndexQuery.getCategory1Id()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category1Id").value(albumIndexQuery.getCategory1Id())));
        }
        if (null != albumIndexQuery.getCategory2Id()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category2Id").value(albumIndexQuery.getCategory2Id())));
        }
        if (null != albumIndexQuery.getCategory3Id()) {
            boolQueryBuilder.filter(f -> f.term(t -> t.field("category3Id").value(albumIndexQuery.getCategory3Id())));
        }

        //3.判断当前是否根据属性和属性值过滤
        List<String> attributeList = albumIndexQuery.getAttributeList();
        //判断
        if (!CollectionUtils.isEmpty(attributeList)) {
            for (String attribute : attributeList) {
                //对每一组进行分割;
                String[] split = attribute.split(":");
                //判断
                if (null != split && split.length == 2) {
                    //封装属性与属性值数据
                    boolQueryBuilder.filter(f -> f.nested(n -> n.path("attributeValueIndexList")
                            .query(q -> q.bool(b -> b.filter(f1 -> f1.term(t -> t.field("attributeValueIndexList.attributeId").value(split[0])))
                                    .filter(f2 -> f2.term(t -> t.field("attributeValueIndexList.valueId").value(split[1])))))));
                }


            }
        }
        //4.判断用户根据什么进行排序 综合排序[1:desc] 播放量[2:desc] 发布时间[3:desc]；asc:升序 desc:降序
        String order = albumIndexQuery.getOrder();
        if (!StringUtils.isEmpty(order)) {
            String[] split = order.split(":");
            if (null != split && split.length == 2) {
                String orderField = "";
                switch (split[0]) {
                    case "1":
                        //综合排序 1
                        orderField = "hotScore";
                        break;
                    case "2":
                        //播放量排序 2
                        orderField = "playStatNum";
                        break;
                    case "3":
                        //发布时间排序 3
                        orderField = "createTime";
                }
                //  重置排序字段名称
                String finalOrderField = orderField;
                searchRequestBuilder.sort(s -> s.field(f -> f.field(finalOrderField).order("asc".equals(split[1]) ? SortOrder.Asc : SortOrder.Desc)));
            }
        }
        //分页查
        searchRequestBuilder.from((albumIndexQuery.getPageNo() - 1) * albumIndexQuery.getPageSize());
        searchRequestBuilder.size(albumIndexQuery.getPageSize());
        //设置bool
        BoolQuery boolQuery = boolQueryBuilder.build();
        //设置query-->bool
        searchRequestBuilder.query(boolQuery._toQuery());
        //返回对象
        SearchRequest searchRequest = searchRequestBuilder.build();
        System.out.println("dsl:\t" + searchRequest.toString());
        return searchRequest;
    }
}
